if(typeof(BaseUtil)=="undefined" || !BaseUtil){
    BaseUtil={};
}

(function(exports){

    /**
     * 获取jquery对象
     * @param obj
     */
    function getJQuery(obj) {
        if(obj) {
            if(obj instanceof jQuery) {
                return obj;
            }else {
                return $(obj);
            }
        }
    }
    
    function serializeMapContainer(obj) {
        var list = serializeArrayContainer(obj);
        var map={};
        for(var i=0;i<list.length;i++){
            var n=list[i].name;
            var v=list[i].value;
            var value=map[n];
            if(typeof(value)=="undefined"){
                map[n]=v;
                continue;
            }
            if($.isArray(value)){
                value.push(v);
            }
            else{
                value=[value];
                value.push(v);
                map[n]=value;
            }
        }
        return map;
    }

    /**
     * 序列化指定区域的表单数据
     * 复制的Jquery serializeArray方法
     * @param obj
     */
    function serializeArrayContainer(obj) {
        var rbracket = /\[\]$/,
            rCRLF = /\r?\n/g,
            rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,
            rsubmittable = /^(?:input|select|textarea|keygen)/i;
        var rcheckableType = ( /^(?:checkbox|radio)$/i );

        var $obj = BaseUtil.getJQuery(obj);
        var allInputs = $obj.find(":input");
        return allInputs.filter(function () {
            var type = this.type;
            return this.name && !jQuery( this ).is( ":disabled" ) &&
                rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&
                ( this.checked || !rcheckableType.test( type ) );
        }).map(function (i, elem) {
            var val = jQuery( this ).val();

            if ( val == null ) {
                return null;
            }

            if ( Array.isArray( val ) ) {
                return jQuery.map( val, function( val ) {
                    return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
                } );
            }

            return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
        }).get();
    }

    /**
     * 检测两个URL是否相同
     */
    /**
     * 对函数增加,前置执行方法和后置执行方法.   返回新的方法
     * 前置函数/原始函数的返回都会作为参数放入到后一个函数中.  相当于: 原函数会多一个参数,后置函数多两个参数
     * 如果后置函数有返回则,会覆盖原始返回结果
     * 前函数: 可以控制是否继续原函数,但是无返回值
     * 后函数: 参数最后一个表示原函数的返回值,可以替换返回值
     */
    function appendFunction(fun,beforeFun,afterFun){
        return function(){
            var args=getArgs(arguments);
            var re;		//前返回,返回,后返回值
            if(typeof(beforeFun)=="function"){
                if((re=beforeFun.apply(this,args))==false)return re;
            }
            if(typeof(fun)=="function"){
                re=fun.apply(this,args);
            }
            if(typeof(afterFun)=="function"){
                args.push(re);
                var r=afterFun.apply(this,args);
                if(typeof(r)!="undefined")re=r;
            }
            return re;
        };
    }

    /**
     * 将arguments对象转换成数组. 并且将后面的参数放入到返回的数组后面
     * @param args 表示arguments对象
     */
    function getArgs(args){
        var re=[];
        for(var i=0;i<args.length;i++)re.push(args[i]);
        for(var i=1;i<arguments.length;i++)re.push(arguments[i]);
        return re;
    }

    /**
     * 验证值是否有效,否则返回默认值. 	如果: 类型undefined/字符串undefined/null/字符串""/字符串null/无效字符串	返回默认值
     * 支持多参数进行判断. 例如: checkDefault(val,d1,d2,d3);
     */
    function checkDefault(val,def){
        var vals=Array.prototype.slice.call(arguments);
        for(var i=0;i<vals.length;i++){
            val=vals[i];
            if(checkValue(val))break;
        }
        return val;
    }

    /**
     * 判断值是否是有效.如果: 类型undefined/字符串undefined/null/字符串""/字符串null/无效字符串	返回false
     */
    function checkValue(val){
        if(typeof(val)=="undefined" || val==null || (typeof(val)=="string"&&(val==""||val=="null"||val=="undefined"))
            || (typeof(val)=="number"&&!isFinite(val))){
            return false;
        }
        return true;
    }

    /**
     * 验证当前对象是否为方法 复制jquery的isFunction方法
     * @param obj
     * @returns {boolean|boolean}
     */
    function isFunction(obj) {
        return typeof obj === "function" && typeof obj.nodeType !== "number";
    }

    function callFunction(fun, ctx) {
        if(!isFunction(fun)) return;
        var args=Array.prototype.slice.call(arguments,2)||[];
        return fun.apply(ctx,args);
    }

    function applyFunction(fun,ctx,args){
        if(typeof(fun)!="function")return;
        args=args||[];
        return fun.apply(ctx,args);
    }

    /**
     * 验证对象是位为object
     * @param obj
     */
    function isObject(obj) {
        if(obj == null) return false;
        if(typeof (obj) === "object") return true;
        return false;
    }

    /**
     * 判断对象是否是数组.对象存在length属性且有splice方法
     */
    function isArray(obj){
        if(typeof(Array.isArray)=="function")return Array.isArray(obj);
        return getType(obj)=="Array";
    }


    exports.getJQuery=getJQuery;
    exports.getFormData=serializeMapContainer;
    exports.appendFunction=appendFunction;
    exports.getArgs=getArgs;
    exports.checkDefault=checkDefault;
    exports.checkValue=checkValue;

    exports.isFunction = isFunction;
    exports.callFunction = callFunction;
    exports.applyFunction = applyFunction;
    exports.isObject = isObject;
    exports.isArray = isArray;
})(BaseUtil);

(function (exports) {

    /**
     * 通过URL和附加参数生成数据
     * @param url
     * @param datas
     * @param skipEmpty		跳过空参数					默认false
     * @param keepExists	保持已经url中已经存在的字段	默认false
     * @returns
     */
    function buildUrl(url,datas,skipEmpty,keepExists){
        skipEmpty=BaseUtil.checkDefault(skipEmpty,false);
        keepExists=BaseUtil.checkDefault(keepExists,false);
        /** 准备改成datas中参数覆盖url中的参数
         * */

        if(!keepExists){	//如果需要覆盖原来已经存在的数据
            var path=BaseUtil.getUrlPath(url);
            var params= $.extend(BaseUtil.parseQueryToMap(url),datas);
            var query=buildQuery(params);
            return query?(path+"?"+query):path;
        }

        //下面表示不需要覆盖原来存在的数据
        var query=buildQuery(datas,skipEmpty);
        var hasQu= url.lastIndexOf("?")>-1;	//是否已经有问号
        var endQu= (hasQu && url.lastIndexOf("?")==(url.length-1));
        if(query){
            if(hasQu)url=url+(endQu?"":"&")+query;
            else url=url+"?"+query;
        }
        return url;
    }

    /**
     * 获取URL中的path部分. 注意:url中?和#只能出现一次  例如: http://xx.com/abc/1.jsp?name=1#xx    获取到  /abc/1.jsp
     * 如果url未传入则使用location.pathname
     */
    function getUrlPath(url){
        if(!url){
            if((typeof(document)!="undefined"))return document.location.pathname;
            else{
                return "/";
            }
        }
        var index=url.indexOf("://");
        if(index>-1)index=index+3;
        index=url.indexOf("/",index);
        url=url.substring(index);
        url=url.substringBy2("","#").substringBy2("","?");
        return url;
    }

    /**
     * 构建URL中的query部分
     */
    function buildQuery(datas,skipEmpty){
        var querys=[];
        if(datas){
            for(var i in datas){
                var v=datas[i];
                if(!v&&skipEmpty)continue;
                if(BaseUtil.isArray(v)){
                    for(var ii=0;ii<v.length;ii++){
                        querys.push("{}={}".format(i,v[ii]));
                    }
                }
                else{
                    querys.push("{}={}".format(i,v));
                }
            }
        }
        return querys.join("&");
    }

    /**
     * 获取url的query部分,格式  {name:xx}
     * 如果重复名称仅能获取到单个值
     * keepEmpty	保持空参数
     * filter	接收参数(key,value) 返回false跳过参数,其他值返回则替换原始value
     */
    function parseQueryToObject(url,keepEmpty,filter){
        if(!url)return {};
        var query=url.substringBy2("?","");
        var rs={};
        var ss=query.split("&");
        if(ss&&ss.length>0){
            for(var i=0;i<ss.length;i++){
                var s=String(ss[i]).trimstring();
                if(!s)continue;
                var name=s.substringBy2("","=");
                var value=decodeURIComponent(s.substringBy("=",""));
                if(typeof(filter)=="function"){
                    var re=filter.call(this,name,value);
                    if(re===false)continue;
                    else if(typeof(re)!="undefined"){
                        value=re;
                    }
                }
                if(keepEmpty||BaseUtil.checkValue(value)){
                    rs[name]=value;
                }
            }
        }
        return rs;
    }

    /**
     * 获取url的query部分,格式  {name:[]}
     * keepEmpty	保持空参数
     * filter	接收参数(key,value) 返回false跳过参数,其他值返回则替换原始value
     */
    function parseQueryToMap(url,keepEmpty,filter){
        if(!url)return {};
        var query=url.substringBy2("?","");
        var rs={};
        var ss=query.split("&");
        if(ss&&ss.length>0){
            for(var i=0;i<ss.length;i++){
                var s=String(ss[i]).trimstring();
                var name=s.substringBy2("","=");
                var value=decodeURIComponent(s.substringBy("=",""));
                if(typeof(filter)=="function"){
                    var re=filter.call(this,name,value);
                    if(re===false)continue;
                    else if(typeof(re)!="undefined"){
                        value=re;
                    }
                }
                var array=rs[name];
                if(typeof(array)=="undefined"){
                    rs[name]=array=[];
                }
                if(keepEmpty||BaseUtil.checkValue(value)){
                    array.push(value);
                }
            }
        }
        return rs;
    }

    /**
     * 将url中query部分转换成{name:[]}格式
     */
    function getParameterMap(url){
        if(typeof(url)=="undefined")url=window.location.search;
        else{
            url=url.substringBy("?","");
        }
        return parseQueryToMap(url);
    }

    /**
     * 将url中query部分转换成{name:value}格式
     */
    function getParameterObject(url){
        if(typeof(url)=="undefined")url=window.location.search;
        else{
            url=url.substringBy("?","");
        }
        return BaseUtil.parseQueryToObject(url);
    }

    /**
     * 获取参数,返回单个
     * url		如果为空,则使用默认的
     */
    function getParameter(name,url){
        var map=getParameterObject(url);
        var re=map[name];
        if(typeof(re)=="undefined")return null;
        return re;
    }
    /**
     * 获取参数,返回数组
     */
    function getParameters(name,url){
        var map=getParameterMap(url);
        var re=map[name];
        if(typeof(re)=="undefined")return null;
        return re;
    }

    exports.buildUrl=buildUrl;
    exports.getUrlPath=getUrlPath;
    exports.parseQueryToMap=parseQueryToMap;
    exports.buildQuery=buildQuery;
    exports.parseQueryToObject=parseQueryToObject;
    exports.getParameterMap=getParameterMap;
    exports.getParameterObject=getParameterObject;
    exports.getParameter=getParameter;
    exports.getParameters=getParameters;
})(BaseUtil);

/**
 * 与substringBy2区别在于.此函数在双端未找到时返回""
 * 通过指定标记切取字符串.s1从前查找.s2从后查找,self表示是否需要标志自身
 * 如果未查询到前后标记则会返回空
 */
String.prototype.substringBy=function(s1,s2,self){
    var str=""+this;
    s1=s1||"";
    s2=s2||"";
    if(str.length<(s1.length+s2.length))return "";
    var i1=str.indexOf(s1);
    var i2=str.lastIndexOf(s2);
    if(i1==-1||i2==-1)return "";
    if(!self){
        i1=i1+s1.length;
    }
    else{
        i2=i2+s2.length;
    }
    return str.substring(i1,i2);
};

/**
 * 与substringBy区别在与.此函数在双端未找到时返回原字符串本身
 * 通过指定标记切取字符串.s1从前查找.s2从后查找,self表示是否需要标志自身
 * 如果 前后都没找到则返回 原字符串
 * 找到一边则通过一边切取.
 */
String.prototype.substringBy2=function(s1,s2,self){
    var str=""+this;
    s1=s1||"";
    s2=s2||"";
    if(str.length<(s1.length+s2.length))return str.toString();
    var i1=str.indexOf(s1);
    var i2=str.lastIndexOf(s2);
    if(i1==-1||i2==-1)return str.toString();
    if(!self){
        i1=i1+s1.length;
    }
    else{
        i2=i2+s2.length;
    }
    return str.substring(i1,i2);
};

//增强型trimstring方法.允许去掉开始或结尾的指定字符
String.prototype.trimstring=function(s){
    var str=""+this;
    var t=str.replace(/(^\s*)|(\s*$)/g, "");	//去除空白
    if(t&&s){
        var i1=0;
        while((i1=t.indexOf(s))==0)t=t.substring(s.length);
        while((i1=t.lastIndexOf(s))==(t.length-s.length)){
            if(i1<0)break;
            t=t.substring(0,i1);
        }
    }
    return t;
};

/**
 * 格式化字符串的方法,  {0} 取后面的参数,或者{}依次取后面参数
 */
String.prototype.format = function() {
    var args = arguments,index=0;
    var str=""+this;
    return str.replace(/\{(\d*)\}/g, function(m, i) {
        i=parseInt(i)||index;
        index++;
        return BaseUtil.checkDefault(args[i],"");
    });
};